package com.cskaoyan.mall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.cskaoyan.mall.common.constant.RedisConst;
import com.cskaoyan.mall.product.client.SearchApiClient;
import com.cskaoyan.mall.product.dto.*;
import com.cskaoyan.mall.product.mapper.SpuSaleAttrInfoMapper;
import com.cskaoyan.mall.product.mapper.SpuSaleAttrValueMapper;
import com.cskaoyan.mall.product.service.CategoryService;
import com.cskaoyan.mall.product.service.ProductDetailService;
import com.cskaoyan.mall.product.service.SkuService;
import com.cskaoyan.mall.product.service.SpuService;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class ProductDetailServiceImpl implements ProductDetailService {
    @Autowired
    SkuService skuService;
    @Autowired
    SpuService spuService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    SpuSaleAttrValueMapper spuSaleAttrValueMapper;
    @Autowired
    SpuSaleAttrInfoMapper spuSaleAttrInfoMapper;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    SearchApiClient searchApiClient;
    //这个地方先创建一个线程池
    ExecutorService threadPool= Executors.newFixedThreadPool(12);
    @Override
    public ProductDetailDTO getItemBySkuId(Long skuId) {
        //这个地方要判断一下运行的速度
        Date old=new Date();
        ProductDetailDTO productDetailDTO=new ProductDetailDTO();

        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConst.SKULOCK_SUFFIX);
        boolean contains = bloomFilter.contains(skuId);

        if (!contains){
            System.out.println("被布隆过滤器过滤");
            return new ProductDetailDTO();
        }
        //这个地方要调用search内的内容定义商品的热度
        searchApiClient.incrHotScore(skuId);

        //这里写那个好复杂好复杂的接口
        //先把对应的skuInfo查出来
        CompletableFuture<SkuInfoDTO> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoDTO skuInfo = skuService.getSkuInfo(skuId);
            productDetailDTO.setSkuInfo(skuInfo);
            return skuInfo;
        }, threadPool);
        //然后写和skuInfo关联的相关接口
        CompletableFuture<Void> infoThenAccept = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            //然后这里生成那个有点儿复杂的json
            Map<String, Long> valuesSkuJson = spuService.getSkuValueIdsMap(skuInfo.getSpuId());

            //然后我们获取一下sku对应的spu对应的销售属性
            //这里写连表查询吧
            List<SpuSaleAttributeInfoDTO> spuSaleAttrList = skuService.getSpuSaleAttrListCheckBySku(skuInfo.getId(), skuInfo.getSpuId());

            //然后用fastJson转换一下
            String jsonString = JSON.toJSONString(valuesSkuJson);

            //三级类目的完整类目视图？
            //这个地方也要做连表查询
            CategoryHierarchyDTO categoryViewByCategory = categoryService.getCategoryViewByCategoryId(skuInfo.getThirdLevelCategoryId());

            //海报列表
            List<SpuPosterDTO> posterBySpu = spuService.findSpuPosterBySpuId(skuInfo.getSpuId());


            productDetailDTO.setValuesSkuJson(jsonString);
            productDetailDTO.setCategoryHierarchy(categoryViewByCategory);
            productDetailDTO.setSpuPosterList(posterBySpu);
            productDetailDTO.setSpuSaleAttrList(spuSaleAttrList);
        }, threadPool);

        CompletableFuture<Void> skuPriceFuture = CompletableFuture.runAsync(() -> {

            //然后获取商品的价格
            BigDecimal skuPrice = skuService.getSkuPrice(skuId);
            productDetailDTO.setPrice(skuPrice);


        }, threadPool);

        CompletableFuture<Void> skuAttrListFuture = CompletableFuture.runAsync(() -> {
            //参数属性的集合
            //连表查吧
            //也能不连表查，那不连表吧
            List<PlatformAttributeInfoDTO> platformAttributeInfoDTOS = skuService.getPlatformAttrInfoBySku(skuId);
            List<SkuSpecification> skuSpecificationList = new ArrayList<>();
            for (PlatformAttributeInfoDTO info : platformAttributeInfoDTOS) {
                for (PlatformAttributeValueDTO value : info.getAttrValueList()) {
                    SkuSpecification skuSpecification = new SkuSpecification();
                    skuSpecification.setAttrName(info.getAttrName());
                    skuSpecification.setAttrValue(value.getValueName());
                    skuSpecificationList.add(skuSpecification);
                }
            }

            productDetailDTO.setSkuAttrList(skuSpecificationList);

        }, threadPool);


        //这个地方要等待所有线程的执行完毕，这里要用到多元依赖
        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(skuPriceFuture, skuAttrListFuture, skuInfoFuture, infoThenAccept);

        completableFuture.join();

        Date fresh=new Date();
        System.out.println("花费的时间"+(fresh.getTime()-old.getTime()));



        return productDetailDTO;
    }
}
